package hunan.qianyuan.codefatherback.ai;

import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import dev.langchain4j.community.store.memory.chat.redis.RedisChatMemoryStore;
import dev.langchain4j.data.message.ToolExecutionResultMessage;
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.model.chat.StreamingChatModel;
import dev.langchain4j.service.AiServices;
import hunan.qianyuan.codefatherback.ai.guardrail.PromptSafetyInputGuardrail;
import hunan.qianyuan.codefatherback.ai.guardrail.RetryOutputGuardrail;
import hunan.qianyuan.codefatherback.ai.model.enums.CodeGenTypeEnum;
import hunan.qianyuan.codefatherback.ai.tools.*;
import hunan.qianyuan.codefatherback.exception.BusinessException;
import hunan.qianyuan.codefatherback.exception.ErrorCode;
import hunan.qianyuan.codefatherback.service.ChatHistoryService;
import hunan.qianyuan.codefatherback.utils.SpringContextUtil;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Configuration;

import java.time.Duration;

@Slf4j
@Configuration
public class AiCodeGeneratorServiceFactory {

    @Resource(name = "openAiChatModel")
    private ChatModel chatModel;


    @Resource
    @Qualifier("streamingChatModelPrototype")
    private StreamingChatModel openAiStreamingChatModel;

    @Resource
    @Qualifier("reasoningStreamingChatModelPrototype")
    private StreamingChatModel reasoningStreamingChatModel;

    @Resource
    private RedisChatMemoryStore redisChatMemoryStore;

    @Resource
    private ChatHistoryService chatHistoryService;

    private final Cache<String, AiCodeGeneratorService> serviceCache = Caffeine.newBuilder()
            .maximumSize(1000)
            .expireAfterWrite(Duration.ofMinutes(30))
            .expireAfterAccess(Duration.ofMinutes(10))
            .removalListener((key, value, cause) -> {
                log.debug("AI服务实例被移除，appId:{},原因：{}", key, cause);
            }).build();


    /**
     * 根据appId和类型创建AiCodeGeneratorService
     */
    public AiCodeGeneratorService createAiCodeGeneratorService(long appId, CodeGenTypeEnum codeGenTypeEnum) {
        MessageWindowChatMemory chatMemory = MessageWindowChatMemory.builder()
                .maxMessages(50)
                .id(appId)
                .chatMemoryStore(redisChatMemoryStore)
                .build();
        chatHistoryService.loadChatHistoryToMemory(appId, chatMemory, 50);

        switch (codeGenTypeEnum) {
            case VUE_PROJECT -> {
                StreamingChatModel reasoningStreamingChatModel = SpringContextUtil.getBean("reasoningStreamingChatModelPrototype", StreamingChatModel.class);
                return AiServices.builder(AiCodeGeneratorService.class)
                        .chatModel(chatModel)
                        .streamingChatModel(reasoningStreamingChatModel)
                        .inputGuardrailClasses(PromptSafetyInputGuardrail.class)
                        .outputGuardrails(new RetryOutputGuardrail())
                        .chatMemoryProvider(memoryId -> chatMemory)
                        .tools(
                                new FileWriteTool(),
                                new FileReadTool(),
                                new FileModifyTool(),
                                new FileDirReadTool(),
                                new FileDeleteTool()
                        )
                        .hallucinatedToolNameStrategy(toolExecutionRequest ->
                                ToolExecutionResultMessage.from(toolExecutionRequest, "工具使用错误：" + toolExecutionRequest.name()))
                        .build();
            }
            case HTML, MULTI_FILE -> {
                StreamingChatModel streamingChatModelPrototype = SpringContextUtil.getBean("streamingChatModelPrototype", StreamingChatModel.class);
                return AiServices.builder(AiCodeGeneratorService.class)
                        .chatModel(chatModel)
                        .streamingChatModel(streamingChatModelPrototype)
                        .chatMemory(chatMemory)
                        .build();
            }

            default ->
                    throw new BusinessException(ErrorCode.SYSTEM_ERROR, "不支持的代码生成模式" + codeGenTypeEnum.getValue());
        }
    }

    /**
     * 从缓存获取或创建AiCodeGeneratorService
     */
    public AiCodeGeneratorService getAiCodeGeneratorService(long appId, CodeGenTypeEnum codeGenTypeEnum) {
        String cacheKey = buildCacheKey(appId, codeGenTypeEnum);
        return serviceCache.get(cacheKey, key -> createAiCodeGeneratorService(appId, codeGenTypeEnum));
    }

    /**
     * 构建缓存键
     */
    public String buildCacheKey(long appId, CodeGenTypeEnum codeGenTypeEnum) {
        return appId + "_" + codeGenTypeEnum.getValue();
    }

}
